#!/usr/bin/python2

"""
Assembler for instruction
"""
import sys
try:
    output_file = open(sys.argv[2], 'w')
except Exception as e:
    output_file = sys.stdout

input_file = open(sys.argv[1], 'r')

prefix_dict = {'add':'00000000',
               'sub':'00000001',
               'setl':'10010010',
               'seth':'10010011',
               'ld':'00100000',
               'st':'00110000',
               'jeq':'01010001',
               'jlt':'01110001',
               }
labels = {}
curraddr = 0
code_dict = {}

def toBinary(x, width):
    return bin(eval(str(x)) % (1 << width))[2:].zfill(width)

lines = input_file.readlines()
print lines
#handle labels
for line in lines:
    line = line.strip()
    #skip empty line and comment
    if len(line) == 0 or line[0] == '#':
        continue
    #handle labels
    if line[-1] == ':':
        labels[line[:-1]] = curraddr
        continue
    code_dict[curraddr] = line
    curraddr = curraddr + 1

for k in labels:
    print "#", k, labels[k]
print " "

for k in code_dict:
    print k,code_dict[k]
print ""

curraddr = 0
nop = "imem[+NUM+]<=32'b00000000000000000000000000000000"

for line in lines:
    line = line.strip()
    #skip empty line and comment
    if len(line) == 0 or line[0] == '#':
        print "// " + line
    elif line[-1] == ':':
        print "// " + line
    else:
        s = "imem[%d]<=32'b" % curraddr
        parts = line.split()
        s = s + prefix_dict[parts[0]]
        if parts[0] == 'add' or parts[0] == 'sub' or parts[0] == 'ld' or parts[0] == 'st':
            s += toBinary(parts[2][1:], 5) + toBinary(parts[3][1:], 5) + toBinary(parts[1][1:], 5) + '000000000'
        elif parts[0] == 'setl' or parts[0] == 'seth':
            s += toBinary(parts[1][1:], 5) + '000' + toBinary(parts[2], 16)
        elif parts[0] == 'jeq' or parts[0] == 'jlt':
            s += toBinary(parts[1][1:], 5) + toBinary(parts[2][1:], 5)
            offset = 0
            try:
                offset = int(parts[3])
            except:
                try:
                    offset = labels[parts[3]] - curraddr
                except:
                    pass
            s += toBinary(offset, 14)
        print s+";"
        curraddr = curraddr + 1
#        print nop.replace("+NUM+", str(curraddr))+";"
#        curraddr = curraddr + 1
#        print nop.replace("+NUM+", str(curraddr))+";"
#        curraddr = curraddr + 1
#        print nop.replace("+NUM+", str(curraddr))+";"
#        curraddr = curraddr + 1
#        print nop.replace("+NUM+", str(curraddr))+";"
#        curraddr = curraddr + 1
#        print nop.replace("+NUM+", str(curraddr))+";"
#        curraddr = curraddr + 1
